#include "widget.h"
#include "ui_widget.h"
#include "iostream"
#include <QOpenGLShader>
#include <QVector4D>
#include <QtMath>
#include <QImage>
#include <QKeyEvent>

using namespace std;

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent),VBO(QOpenGLBuffer::VertexBuffer), EBO(QOpenGLBuffer::IndexBuffer)
    //, ui(new Ui::Widget)
{
    //ui->setupUi(this);
}

Widget::~Widget()
{
    //delete ui;
    delete camera;
    delete texture1;
}

unsigned int indices[] = {
    // 注意索引从0开始!
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标，
    // 这样可以由下标代表顶点组合成矩形

    0, 1, 3, // 第一个三角形
    1, 3, 2  // 第二个三角形
};
void Widget::initializeGL() {
    float vertices[] = {
    //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
    };
    this->initializeOpenGLFunctions();
    camera = new Camera(QVector3D(0,0,3), width(), height());
    ourShader.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/shader/model_loading.vert");
    ourShader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/shader/model_loading.frag");
    ourShader.link();

    ourModel=new Model("D:/selfad/alg_and_graph/qt-opengl/opengl-functionlearn10model/nanosuit/nanosuit.obj");
    //ourModel=new Model("D:/selfad/qtapp/qt-with-open-gl/objects/planet/planet.obj");
    //ourModel=new Model("D:/selfad/qtapp/qt-with-open-gl/objects/cyborg/cyborg.obj");


//    QOpenGLVertexArrayObject::Binder{&VAO};
//    EBO.create();
//    EBO.bind();
//    EBO.allocate(indices,sizeof(indices));

//    VBO.create();       //生成VBO对象
//    VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中
//    //将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
//    VBO.allocate(vertices,sizeof(vertices));
//    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof (GLfloat), (void*)0);

//    glEnableVertexAttribArray(0);

//    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof (GLfloat), (void*)(3* sizeof(float)));
//    glEnableVertexAttribArray(1);

//    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof (GLfloat), (void*)(6* sizeof(float)));
//    glEnableVertexAttribArray(2);

//    // VAO.release();      //解绑VAO，安全使用

//     texture1 = new QOpenGLTexture(QImage("D:/selfad/LearnOpenGL/resources/textures/container.jpg"));
//     texture1->setWrapMode(QOpenGLTexture::Repeat);
//     texture1->setMinificationFilter(QOpenGLTexture::Nearest);
//     texture1->setMagnificationFilter(QOpenGLTexture::Linear);
}
void Widget::paintGL()
{
    camera->DealKeyboardInputs();
   // cout<<"paint GL"<<endl;
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);


    QMatrix4x4 projection;

    projection.perspective(camera->zoom, GLfloat(this->width())/GLfloat(this->height()), 0.1f, 100);
    ourShader.setUniformValue("projection",projection);
    ourShader.setUniformValue("view",camera->getViewMat());
    ourShader.setUniformValue("model",QMatrix4x4());

    ourModel->Draw(ourShader);
    //ourShader.bind();
    //QOpenGLVertexArrayObject::Binder{&VAO};
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    update();
}
void Widget::resizeGL(int w, int h){
    cout<<"w : "<< w<< "h : "<<h<< endl;
}

void Widget::keyPressEvent(QKeyEvent *event) {
    cout<<"key: down" <<endl;
    camera->keys[event->key()]=GL_TRUE;
}

void Widget::keyReleaseEvent(QKeyEvent *event) {
    cout<<"key: up" <<endl;
    if(event->key()<0 || event->key()>=1024)return;
    camera->keys[event->key()]=GL_FALSE;
}


void Widget::mousePressEvent(QMouseEvent *event){
    cout<<"mouse: down" <<endl;
    if(event->button() == Qt::LeftButton) camera->isLeftMousePress = GL_TRUE;
}
void Widget::mouseReleaseEvent(QMouseEvent *event){
    cout<<"mouse: release" <<endl;
    if(event->button()==Qt::LeftButton) {
        camera->isLeftMousePress = GL_FALSE;
        camera->isFirstMouse = GL_TRUE;
    }
}
void Widget::mouseMoveEvent(QMouseEvent *event){
    cout<<"mouse: move" <<endl;
    GLint xpos = event->pos().x();
    GLint ypos = event->pos().y();

    if(camera->isLeftMousePress) {
        if(camera->isFirstMouse) {
            camera->lastX=xpos;
            camera->lastY = ypos;
            camera->isFirstMouse = GL_FALSE;
        }

        GLint Xoffset = xpos - camera->lastX;
        GLint Yoffset = camera->lastY - ypos;
        camera->lastX = xpos;
        camera->lastY = ypos;

        camera->DealMouseMovement(Xoffset, Yoffset);
    }
}
void Widget::wheelEvent(QWheelEvent *event){
    cout<<"wheel: roll" <<endl;
    QPoint offset = event->angleDelta();
    camera->DealMouseScroll(offset.y()/20.0f);
}
